﻿using MIMSDomain.Concrete;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using MIMSDomain.Entities;
using Moq;
using System.Linq;
using System.Collections.Generic;
using MIMSDomain.Abstract;

namespace MIMSUnitTests.Domain
{
    /// <summary>
    ///This is a test class for EFPatientRepositoryTest and is intended
    ///to contain all EFPatientRepositoryTest Unit Tests
    ///</summary>
    [TestClass()]
    public class EFPatientRepositoryTest
    {
        private TestContext testContextInstance;
        public readonly IRepository<Patient> MockPatientRepository;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        public EFPatientRepositoryTest()
        {
            //Arrange
            IList<Patient> patients = new List<Patient>{ 
                new Patient{Id=1,FirstName="John", MiddleName="Adams", LastName="Withaker",Phone="2348036677937"},
                new Patient{Id=2,FirstName="Janet", MiddleName="Adeyemi", LastName="Johnson",Phone="2348057323452"},
                new Patient{Id=3,FirstName="Micheal", MiddleName="Williams", LastName="Smith",Phone="2348098765474"}
            };

            var target = new Mock<IRepository<Patient>>(); 

            target.Setup(p => p.All).Returns(patients.AsQueryable());
            target.Setup(p => p.GetById(It.IsAny<int>())).Returns((int i) => patients.Where(p => p.Id == i).Single());
            target.Setup(p => p.Save(It.IsAny<Patient>())).Returns((Patient objPatient) =>
                {
                    if(objPatient.Id.Equals(default(int))){
                        objPatient.Id = patients.Count() + 1;
                        patients.Add(objPatient);
                    }else{
                        var original = patients.Where(p => p.Id == objPatient.Id).Single();
                        if(original == null){
                            return false;
                        }
                        //more fields will be added as the patient entity matures.
                        original.Code = objPatient.Code;
                        original.FirstName = objPatient.FirstName;
                        original.MiddleName = objPatient.MiddleName;
                        original.LastName = objPatient.LastName;
                        original.Phone = objPatient.Phone;
                    }
                    return true;
                });
            target.Setup(p => p.Delete(It.IsAny<Patient>())).Returns((Patient objPatient) => 
                {
                    if (patients.Contains(objPatient))
                    {
                        patients.Remove(objPatient);
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                });
            MockPatientRepository = target.Object;
        }
        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for SavePatient
        ///</summary>
        [TestMethod()]
        public void CanSavePatient()
        {
            //Arrange
            var count = MockPatientRepository.All.Count();
            //Assert
            Assert.AreEqual(3,count);
            //Act 
            var actual = MockPatientRepository.Save(new Patient { FirstName="Temitope", MiddleName="Adeyemi", LastName="Jaja", Phone="+2348057766458" });
            //Assert
            Assert.AreEqual(4, MockPatientRepository.All.Count());
        }

        /// <summary>
        ///A test for GetPatientById
        ///</summary>
        [TestMethod()]
        public void CanGetPatientById()
        {
            //Act
            var expected = this.MockPatientRepository.GetById(1);
            //Assert
            Assert.IsNotNull(expected);
            Assert.IsInstanceOfType(expected, typeof(Patient));
            Assert.AreEqual("John", expected.FirstName);
        }

        /// <summary>
        ///A test for DeletePatient
        ///</summary>
        [TestMethod()]
        public void CanDeletePatient(){
            //Arrange
            var count = MockPatientRepository.All.Count();
            var objPatient = MockPatientRepository.GetById(2);
            //Assert
            Assert.AreEqual(3,count);
            Assert.IsNotNull(objPatient);
            Assert.IsInstanceOfType(objPatient, typeof(Patient));
            //Act
            var actual = MockPatientRepository.Delete(objPatient);
            //Assert
            Assert.AreEqual(2, MockPatientRepository.All.Count());
        }

        [TestMethod()]
        [ExpectedException(typeof(InvalidOperationException))]
        public void CannotSavePatientWithDuplicateMSISDN()
        {
            throw new NotImplementedException();
        }
    }
}
